/*
* Copyright (c) 2009, Active Web Solutions Limited
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1- Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2- Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3- The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY Active Web Solutions Limited ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Active Web Solutions Limited BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package net.aws.jazure;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import net.aws.jazure.conf.ConfigurationProperties;
import net.aws.jazure.exception.APIRequestFailedException;
import net.aws.jazure.httpconstants.CompConstants;
import net.aws.jazure.httpconstants.QueryParams;
import net.aws.jazure.httpconstants.XMLElements;
import net.aws.jazure.util.RestHelper;

import org.restlet.Client;
import org.restlet.data.ChallengeResponse;
import org.restlet.data.ChallengeScheme;
import org.restlet.data.Method;
import org.restlet.data.Protocol;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * <p>
 * The entry point of the Queue Storage API.
 * </p>
 * @author dyaa.albakour
 *
 */
public class QueueStorage {
	
	private String accountName;
	private String accountSharedKey;
	private String endPoint;
	
	/**
	 * Create a new QueueStorage instance using the account information provided in the
	 * configuration file
	 */
	public QueueStorage() {
		super();
		this.accountName = ConfigurationProperties.getInstance().getProperty(ConfigurationProperties.AccountName);
		this.accountSharedKey = ConfigurationProperties.getInstance().getProperty(ConfigurationProperties.AccountSharedKey);;
		this.endPoint = ConfigurationProperties.getInstance().getProperty(ConfigurationProperties.QueueStorageEndpoint);
	}

	/**
	 * Create a new QueueStorage instance with the given storage account and credentials.
	 * 
	 * @param endPoint
	 * @param accountName
	 * @param accountSharedKey
	 */
	public QueueStorage(String endPoint, String accountName, String accountSharedKey) {
		this.endPoint = endPoint;
		this.accountName = accountName;
		this.accountSharedKey = accountSharedKey;
	}
	
	/**
	 * Get a reference to a newly created <code>Queue</code> object.
	 *  This method does not make any calls to the storage service.
	 * 
	 * @param name The name of the queue.
	 * @return A reference to the newly created <code>Queue</code> object.
	 */
	public Queue getQueue(String name) {
		return new Queue(endPoint,name,accountName,accountSharedKey);
	}
	
	
	/**
	 * List the queues in the Queue Storage account.
	 * @return A List of the <code>Queue</code> objects in the account or null 
	 * 			if the XML response is not parsed correctly.
	 * @throws APIRequestFailedException If the API request return an unexpected HTTP status code.
	 */
	public List<Queue> listQueues() 
		throws APIRequestFailedException {
		try{
			Client client = new Client(Protocol.HTTP); 
			ChallengeResponse challengeResponse =  new ChallengeResponse(
		    	ChallengeScheme.HTTP_MS_SHAREDKEY,
		    	accountName,
		    	accountSharedKey);
			
			Map<String, String> parameters= new HashMap<String, String>();
			parameters.put(QueryParams.QueryParamComp, CompConstants.List);
			
			String url = RestHelper.createRequestURI(endPoint+"/",parameters);
			
			Request request = new Request(Method.GET, url);
			request.setChallengeResponse(challengeResponse);
			Response response = client.handle(request); 
			
			if (response.getStatus().equals(Status.SUCCESS_OK)) {
	  
				Representation representation = response.getEntity();   
	
				List<Queue> queues = new ArrayList<Queue>();
			
				BufferedReader rd = new BufferedReader(new InputStreamReader(representation.getStream(), "UTF-8"));
				// Due to Java bug, skip the first character 
				// (see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058)
		        rd.skip(1);
		        
				NodeList queueNames=
					DocumentBuilderFactory.newInstance().newDocumentBuilder().
					parse(new InputSource(rd)).getElementsByTagName(XMLElements.QueueName);
				
							
				for (int i = 0; i < queueNames.getLength(); i++) {
				
					Node node = queueNames.item(i);
					String queueName = node.getTextContent();
					
					queues.add(new Queue(endPoint,queueName,accountName,accountSharedKey));
				}
			
				return queues;
			}else
				throw new APIRequestFailedException(response.getStatus());
		} catch (UnsupportedEncodingException e) {
			// createRequestURI failed
			return null;
		} catch (IOException e) {
			//representation.getStream()
			return null;
		} catch (SAXException e) {
			// XML parsing failed
			return null;
		} catch (ParserConfigurationException e) {
			// XML parsing failed.
			return null;
		}	
	}
	
}
